<template>
  <div class="statement scrollbar-wrap">
    <div class="statement-head">
      <span>
        <header-select @selectProject="getProject" />
      </span>
      <el-row class="legend-container">
        <el-col :span="12" class="legend-item">
          <span class="legend-item-block" style="background-color: #1826b1" />
          <span>主体</span>
        </el-col>
        <el-col :span="12" class="legend-item">
          <span class="legend-item-block" style="background-color: #ff6a6a; height: 6px" />
          <span>预售</span>
        </el-col>
      </el-row>
    </div>
    <!--<el-scrollbar
      v-loading="loading"
      style="height: calc(100vh - 140px);"
      element-loading-text="拼命加载中..."
    >
      <div
        v-for="(item, index) in buildingData"
        :key="index"
        :name="index"
        class="building-schedule"
        @click="gotoBuildingDetail(item.buildingId, item.buildingName)"
      >
        <BodyCharts :data="item" style="height: 200px" />
        <div class="building-name" style="height: 35px">{{ item.buildingName }}</div>
      </div>
    </el-scrollbar>-->
    <div ref="schedule3DRef" v-loading="loading" element-loading-text="拼命加载中..." style="height: calc(100vh - 140px);" @dblclick="clickModel" />
  </div>
</template>

<script>
import { projectOverall } from '@/api/statement/processSchedule'
import HeaderSelect from './components/HeaderSelect'
import * as THREE from 'three'
import { MapControls } from 'three/examples/jsm/controls/OrbitControls.js'
// import BodyCharts from './components/BodyCharts'
let camera, controls, scene, renderer
export default {
  name: 'ProcessSchedule3D',
  components: {
    HeaderSelect
    // BodyCharts
  },
  data() {
    return {
      /* 整体遮罩 */
      loading: true,
      /* 当前选中项目 */
      currentProject: {},
      imgUrl: require('@/assets/image/floor.png'), // 楼层贴图
      grassUrl: require('@/assets/image/grass.jpg'), // 草坪贴图
      buildingFloor: { x: 24, y: 8, z: 24 }, // 层 x 长，y高，z宽
      /* 楼栋数据 */
      buildings: []
    }
  },
  created() {
  },
  mounted() {
    this.init()
    this.animate()
    this.createGrass()
  },
  methods: {
    /*
    *  点击模型
    * */
    clickModel(event) {
      console.log(scene)
      const raycaster = new THREE.Raycaster()
      const mouse = new THREE.Vector2()
      const scheduleDom = this.$refs.schedule3DRef
      const domRect = scheduleDom.getBoundingClientRect()
      // 将鼠标点击位置的屏幕坐标转换成threejs中的标准坐标
      mouse.x = (event.offsetX / domRect.width) * 2 - 1
      mouse.y = -(event.offsetY / domRect.height) * 2 + 1

      // 通过鼠标点的位置和当前相机的矩阵计算出raycaster
      raycaster.setFromCamera(mouse, camera)

      // 获取raycaster直线和所有模型相交的数组集合
      var intersects = raycaster.intersectObjects(scene.children)
      // 遍历所有的相交的模型
      for (var i = 0; i < intersects.length; i++) {
        const building = intersects[ i ].object.building || null
        if (building) {
          this.gotoBuildingDetail(building.buildingId, building.buildingName)
          break
        }
      }
    },
    /*
    *  创建草坪
    * */
    createGrass() {
      const geometry = new THREE.PlaneGeometry(10000, 10000)
      const texture = new THREE.TextureLoader().load(this.grassUrl)
      texture.wrapS = THREE.RepeatWrapping
      texture.wrapT = THREE.RepeatWrapping
      texture.repeat.set(20, 20)
      const grassMaterial = new THREE.MeshBasicMaterial({ map: texture })
      const grass = new THREE.Mesh(geometry, grassMaterial)
      grass.rotation.x = -0.5 * Math.PI
      scene.add(grass)
    },
    /*
    *  canvas生成楼层纹理
    *  @params：img 图片数据，height 楼层
    * */
    generareCanvasTexture(img, topFloor) { // height 层数
      var canvas = document.createElement('canvas')
      var ctx = canvas.getContext('2d')

      canvas.width = img.width
      canvas.height = topFloor * img.height
      for (let i = 0; i < topFloor; i++) {
        ctx.drawImage(img, 0, i * img.height, img.width, img.height)
      }
      var canvasTexture = new THREE.Texture(canvas)
      canvasTexture.wrapS = THREE.RepeatWrapping
      canvasTexture.wrapT = THREE.RepeatWrapping
      canvasTexture.needsUpdate = true
      return canvasTexture
    },
    /* 创建字体精灵 */
    makeTextSprite(message, parameters) {
      if (parameters === undefined) parameters = {}

      /*eslint-disable*/
      var fontface = parameters.hasOwnProperty('fontface')
        ? parameters['fontface'] : 'Arial'

      /* 字体大小 */
      var fontsize = parameters.hasOwnProperty('fontsize')
        ? parameters['fontsize'] : 30

      /* 边框厚度 */
      var borderThickness = parameters.hasOwnProperty('borderThickness')
        ? parameters['borderThickness'] : 4

      /* 边框颜色 */
      var borderColor = parameters.hasOwnProperty('borderColor')
        ? parameters['borderColor'] : { r: 0, g: 0, b: 0, a: 1.0 }

      /* 背景颜色 */
      var backgroundColor = parameters.hasOwnProperty('backgroundColor')
        ? parameters['backgroundColor'] : { r: 255, g: 255, b: 255, a: 1.0 }
     /*eslint-disable*/

      /* 创建画布 */
      var canvas = document.createElement('canvas')
      var context = canvas.getContext('2d')

      /* 字体加粗 */
      context.font = 'Bold ' + fontsize + 'px ' + fontface
      // context.textAlign = 'right'

      /* 获取文字的大小数据，高度取决于文字的大小 */
      var metrics = context.measureText(message)
      var textWidth = metrics.width

      /* 背景颜色 */
      context.fillStyle = 'rgba(' + backgroundColor.r + ',' + backgroundColor.g + ',' +
    backgroundColor.b + ',' + backgroundColor.a + ')'

      /* 边框的颜色 */
      context.strokeStyle = 'rgba(' + borderColor.r + ',' + borderColor.g + ',' +
    borderColor.b + ',' + borderColor.a + ')'
      context.lineWidth = borderThickness

      /* 绘制圆角矩形 */
      roundRect(context, borderThickness / 2, borderThickness / 2, textWidth + borderThickness, fontsize * 1.4 + borderThickness, 6)

      /* 字体颜色 */
      // context.fillStyle = 'rgba(0, 0, 0, 1.0)'
      context.fillStyle = '#05f8d6'
      context.fillText(message, borderThickness, fontsize + borderThickness)

      /* 画布内容用于纹理贴图 */
      var texture = new THREE.Texture(canvas)
      texture.needsUpdate = true

      var spriteMaterial = new THREE.SpriteMaterial({ map: texture })
      var sprite = new THREE.Sprite(spriteMaterial)

      /* 缩放比例 */
      sprite.scale.set(60, 30, 1)

      return sprite

      /* 绘制圆角矩形 */
      function roundRect(ctx, x, y, w, h, r) {
        ctx.beginPath()
        ctx.moveTo(x + r, y)
        ctx.lineTo(x + w - r, y)
        ctx.quadraticCurveTo(x + w, y, x + w, y + r)
        ctx.lineTo(x + w, y + h - r)
        ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h)
        ctx.lineTo(x + r, y + h)
        ctx.quadraticCurveTo(x, y + h, x, y + h - r)
        ctx.lineTo(x, y + r)
        ctx.quadraticCurveTo(x, y, x + r, y)
        ctx.closePath()
        ctx.fill()
        ctx.stroke()
      }
    },
    init() {
      const scheduleDom = this.$refs.schedule3DRef
      scene = new THREE.Scene()
      // scene.fog = new THREE.FogExp2(0xcccccc, 0.002)
      scene.fog = new THREE.Fog(0xffffff, 10, 1500)
      scene.background = new THREE.Color(0xcce0ff)

      scene.matrixAutoUpdate  = false;
      scene.updateMatrix();

      renderer = new THREE.WebGLRenderer({ antialias: true })
      // renderer.setPixelRatio(window.devicePixelRatio)
      renderer.setPixelRatio(scheduleDom.clientWidth / scheduleDom.clientHeight)
      renderer.setSize(scheduleDom.clientWidth, scheduleDom.clientHeight)
      scheduleDom.appendChild(renderer.domElement)

      camera = new THREE.PerspectiveCamera(60, scheduleDom.clientWidth / scheduleDom.clientHeight, 1, 1000)
      camera.position.set(800, 600, 0)
      // camera.lookAt(500, 0, 0)

      // controls

      controls = new MapControls(camera, renderer.domElement)

      // controls.addEventListener( 'change', render ); // call this only in static scenes (i.e., if there is no animation loop)

      controls.enableDamping = true // an animation loop is required when either damping or auto-rotation are enabled
      controls.dampingFactor = 0.5

      controls.screenSpacePanning = false

      controls.minDistance = 100
      controls.maxDistance = 500

      controls.maxPolarAngle = Math.PI / 2

      // this.updateMeshAndSprite()

      // lights

      const dirLight1 = new THREE.DirectionalLight(0xffffff)
      dirLight1.position.set(1, 1, 1)
      scene.add(dirLight1)

      const dirLight2 = new THREE.DirectionalLight(0x002288)
      dirLight2.position.set(-1, -1, -1)
      scene.add(dirLight2)

      const ambientLight = new THREE.AmbientLight(0x222222)
      scene.add(ambientLight)

      // 坐标系辅助工具
      const axis = new THREE.AxisHelper(2000)
      scene.add(axis)

      window.addEventListener('resize', this.onWindowResize)
    },

    /*
    *  更新网格 与 精灵模型
    * */
    updateMeshAndSprite() {
      for (let i = 0; i < scene.children.length; i++) {
        if (scene.children[i].type === 'Mesh' || scene.children[i].type === 'Sprite') {
          if (scene.children[i].building) {
            scene.remove(scene.children[i])
          }
        }
      }
      const geometry = new THREE.BoxGeometry(1, 1, 1)
      geometry.translate(0, 0.5, 0)
      const img = new Image()
      const position = { x: -200, z: -200 } // 楼栋位置
      img.onload = () => {
        for (let i = 0; i < this.buildings.length; i++) {
          if (this.buildings[i].topFloor < 1) continue
          position.x += 100
          if (position.x > 100) {
            position.x = -200
            position.z += 100
          }
          // 楼栋 网格模型
          const height = this.buildings[i].topFloor * this.buildingFloor.y
          const material = new THREE.MeshPhongMaterial({ map: this.generareCanvasTexture(img, this.buildings[i].topFloor) })
          const materialTop = new THREE.MeshPhongMaterial({ color: 0xa0a0a0 })
          const mesh = new THREE.Mesh(geometry, [material, material, materialTop, material, material, material])
          mesh.position.x = position.x
          mesh.position.y = 0
          mesh.position.z = position.z
          mesh.scale.x = this.buildingFloor.x
          mesh.scale.y = height
          mesh.scale.z = this.buildingFloor.z
          mesh.updateMatrix()
          mesh.matrixAutoUpdate = false
          mesh.building = this.buildings[i]
          scene.add(mesh)

          // 楼栋名称 精灵模型
          var spriteText = this.makeTextSprite(this.buildings[i].buildingName,
            {
              fontsize: 20,
              borderThickness: 6,
              borderColor: { r: 255, g: 255, b: 255, a: 0.9 }, /* 边框黑色 */
              backgroundColor: { r: 255, g: 255, b: 255, a: 0.9 }/* 背景颜色 */
            })
          spriteText.center = new THREE.Vector2(0, 0)
          spriteText.building = this.buildings[i]
          spriteText.position.set(position.x, height, position.z)
          scene.add(spriteText)
        }
      }
      img.src = this.imgUrl
    },

    onWindowResize() {
      const scheduleDom = this.$refs.schedule3DRef
      camera.aspect = scheduleDom.clientWidth / scheduleDom.clientHeight
      camera.updateProjectionMatrix()

      renderer.setSize(scheduleDom.clientWidth, scheduleDom.clientHeight)
    },

    animate() {
      requestAnimationFrame(this.animate)

      controls.update() // only required if controls.enableDamping = true, or if controls.autoRotate = true

      this.render()
    },

    render() {
      renderer.render(scene, camera)
    },

    /* 选择项目 */
    getProject(project) {
      if (!project) {
        this.loading = false
        return
      }
      this.currentProject = project
      this.getBuildingChartData()
    },
    /* 获取楼栋统计数据 */
    getBuildingChartData() {
      this.loading = true
      this.buildings = []
      projectOverall({ projectId: this.currentProject.id }).then(res => {
        if (res.code === 200) {
          this.buildings = res.data
          // this.init()
          // this.animate()
          // this.createGrass()
          this.updateMeshAndSprite()
        }
        setTimeout(() => {
          this.loading = false
        }, 100)
      }).catch(() => { // 接口请求错误处理
        this.loading = false
      })
    },
    /* 点击获取楼栋工序验收情况 */
    gotoBuildingDetail(buildingId, buildingName) {
      this.$router.push({
        path: '/statement/BuildingView',
        query: {
          buildingId: buildingId
        }})
    }
  }
}
</script>
<style scoped lang="scss">
  .statement {
    .statement-head {
      margin: 10px 20px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      .type-tab {
        .tab {
          margin-left: 10px;
        }
      }
      .legend-container {
        width: 20%;
        .legend-item {
          display: flex;
          align-items: center;
          justify-content: center;
          .legend-item-block {
            margin-right: 10px;
            display: inline-block;
            width: 12px;
            height: 12px;
            border-radius: 2px;
          }
        }
      }
    }
  }
  .building-schedule{
    float:left;
    width:200px;
    height: 300px;
    cursor: pointer;
    .building-name{
      color: #666666;
      text-align: center;
      font-weight: bold;
    }
  }
</style>
